package com.lzx.adx.report.job;


import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.PageUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.lzs.adx.commmon.utils.DateUtils;
import com.lzs.adx.commmon.utils.JsonUtils;
import com.lzx.adx.report.bean.mapper.MeiTuanMapper;
import com.lzx.adx.report.bean.mapper.ReportMapper;
import com.lzx.adx.report.cache.AccountLocalCache;
import com.lzx.adx.report.cache.CommonLocalCache;
import com.lzx.adx.report.constant.MediaChannelConstant;
import com.lzx.adx.report.constant.ProductChannelConstant;
import com.lzx.adx.report.dto.AccountDTO;
import com.lzx.adx.report.dto.MeituanOrderDTO;
import com.lzx.adx.report.dto.ReportDTO;
import com.lzx.adx.report.dto.meituan.MeiTuanResponse;
import com.lzx.adx.report.entity.MeituanOrderEntity;
import com.lzx.adx.report.model.huawei.request.HwUploadRequest;
import com.lzx.adx.report.model.meituan.MeituanResponse;
import com.lzx.adx.report.model.meituan.OrderCallBackRequest;
import com.lzx.adx.report.service.MeituanOrderService;
import com.lzx.adx.report.service.ReportService;
import com.lzx.adx.report.util.HwSecureUtil;

import com.lzx.adx.report.util.URLEncoderDecoderTool;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;


import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.*;
import java.util.*;
import java.util.stream.Collectors;

import static com.lzx.adx.report.job.ElmUnionJob.getYesterdayStartingTime;

@Component
@EnableScheduling
@Slf4j
public class MeiTuanJob {

    public static final String token = "888291087d7baa6c72bbc6981f166527";

    public static final String appkey = "fd22acebf82ca9dea2fe6f5f1da6d4de";

    @Resource
    private MeituanOrderService meituanOrderService;

    @Autowired
    private MeiTuanMapper tuanMapper;

    @Autowired
    private ReportMapper reportMapper;

    @Autowired
    private ThreadPoolTaskExecutor reportExecutor;

    @Resource
    private ReportService reportService;

    @Scheduled(cron = "0 */10 * ? * *")
    public void reportEvent() {
        log.info("开始拉取美团数据");
        MeituanResponse orderPageData = getOrderPageData(1);
        if (Objects.isNull(orderPageData) || CollectionUtil.isEmpty(orderPageData.getDataList())) {
            log.info("美团订单暂无数据");
            return;
        }
        Integer totalPage = PageUtil.totalPage(orderPageData.getTotal(), 100);
        if (totalPage > 1) {
            //循环取订单的数据了
            for (int i = 1; i < totalPage; i++) {
                MeituanResponse meituanResponse = getOrderPageData(i);
                core(meituanResponse.getDataList());
            }
        } else {
            core(orderPageData.getDataList());
        }
        log.info("处理美团数据完毕");

    }

    private void core(List<OrderCallBackRequest> dataList) {
        for (OrderCallBackRequest orderCallBackRequest : dataList) {
            //处理美团订单
            orderCallBack(orderCallBackRequest);
        }

    }


    private static MeituanResponse getOrderPageData(long page) {

        TreeMap<String, Object> params = new TreeMap<>();
        params.put("appkey", appkey);
        params.put("ts", String.valueOf(System.currentTimeMillis() / 1000));
        params.put("businessLine", "3");
        params.put("startTime", getBeginTime());
        params.put("endTime", getCurrentDayEndStime());
        params.put("page", String.valueOf(page));
        params.put("limit", "100");
        params.put("sign", genSign(params));

        String s = HttpUtil.get("https://openapi.meituan.com/api/orderList", params);

        JSONObject jsonObject = JSON.parseObject(s);
        String dataList = jsonObject.getString("dataList");
        JSONArray jsonArray = JSON.parseArray(dataList);
        if (Objects.isNull(jsonArray) || jsonArray.size() == 0) {
            return null;
        }
        MeituanResponse meituanResponse = JSONObject.parseObject(s, MeituanResponse.class);
        return meituanResponse;
    }


    public static String getBeginTime() {
        CommonLocalCache instance = CommonLocalCache.getInstance();
        String elmUnionStime = instance.get("mt_stime");
        if (StringUtils.isBlank(elmUnionStime)) {
            String currentDayBegindayStime = getCurrentDayBegindayStime();
            instance.put("mt_stime", getCurrentDayBegindayStime());
            return currentDayBegindayStime;
        } else {
            // 将时间戳转换为 Instant 对象
            Instant instant = Instant.ofEpochMilli(Long.valueOf(elmUnionStime));
            // 这里使用系统默认时区，您可以根据需要选择其他时区
            LocalDateTime localDateTime = instant.atZone(ZoneId.systemDefault()).toLocalDateTime();

            if (localDateTime.isBefore(getYesterdayStartingTime())) {
                return getCurrentDayBegindayStime();
            } else {
                return elmUnionStime;
            }
        }
    }


    public static String getCurrentDayBegindayStime() {
        LocalDateTime yesterdayStartingTime = getStartingTime();
        // 将 LocalDateTime 转换为 Instant
        Instant instant = yesterdayStartingTime.atZone(ZoneId.systemDefault()).toInstant();
        // 获取时间戳值
        long timestamp = instant.toEpochMilli() / 1000;
        return String.valueOf(timestamp);
    }


    public static String getCurrentDayEndStime() {
        LocalDateTime yesterdayStartingTime = getEndTime();
        // 将 LocalDateTime 转换为 Instant
        Instant instant = yesterdayStartingTime.atZone(ZoneId.systemDefault()).toInstant();
        // 获取时间戳值
        long timestamp = instant.toEpochMilli() / 1000;
        return String.valueOf(timestamp);
    }


    public static LocalDateTime getStartingTime() {
        LocalDate yesterday = LocalDate.now().minusDays(0);
        LocalTime midnight = LocalTime.MIDNIGHT;
        return LocalDateTime.of(yesterday, midnight);
    }


    public static LocalDateTime getEndTime() {
        LocalDate yesterday = LocalDate.now().minusDays(0);
        LocalTime midnight = LocalTime.MAX;
        return LocalDateTime.of(yesterday, midnight);
    }


    public static String genSign(TreeMap<String, Object> params) {
        params.remove("sign");
        StringBuilder stringBuilder = new StringBuilder();
        // 替换为「我要推广」-「联盟API接口」页面下的签名秘钥值
        String apiToken = token;
        stringBuilder
                .append(apiToken)
                .append(params.entrySet().stream()
                        .map(entry -> entry.getKey() + entry.getValue())
                        .collect(Collectors.joining()))
                .append(apiToken);
        return md5(stringBuilder.toString());
    }


    public static String md5(String source) {
        String md5Result = null;
        try {
            byte[] hash = org.apache.commons.codec.binary.StringUtils.getBytesUtf8(source);
            MessageDigest messageDigest = MessageDigest.getInstance("MD5");
            messageDigest.update(hash);
            hash = messageDigest.digest();
            md5Result = Hex.encodeHexString(hash);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return md5Result;
    }


    public MeiTuanResponse orderCallBack(OrderCallBackRequest orderCallBackRequest) {
        log.info("接收到【美团】的请求参数为{}", JsonUtils.toJsonString(orderCallBackRequest));
        try {
            String sid = orderCallBackRequest.getSid();
            Map<String, Object> map = new HashMap<>();
            map.put("orderId", orderCallBackRequest.getOrderid());
            map.put("handType", true);
            map.put("limit", true);
            List<MeituanOrderDTO> meituanOrderDTOList = meituanOrderService.list(map);
            if (CollectionUtil.isNotEmpty(meituanOrderDTOList)) {
                log.info("dspId:{} 订单号:{} 已经处理过了无需再处理", sid, orderCallBackRequest.getOrderid());
                return null;
            }
            //先吧数据存储起来
            MeituanOrderDTO meituanOrderDTO = tuanMapper.toMeituanOrder(orderCallBackRequest);
            meituanOrderDTO.setTradeTypes(StringUtils.join(orderCallBackRequest.getTradeTypeList(), ","));
            meituanOrderDTO.setCreateTime(new Date());
            meituanOrderDTO.setUpdateTime(new Date());
            meituanOrderDTO.setExtend(JSON.toJSONString(orderCallBackRequest));
            meituanOrderDTO.setSid(orderCallBackRequest.getSid());
            meituanOrderService.save(meituanOrderDTO);

            //根据时间点去推送
            String paytime = meituanOrderDTO.getPaytime();
            //广告位id
            //请求参数
            Map<String, Object> params = new HashMap<>();
            params.put("ordertime", DateUtils.convertToFormattedDate(Long.parseLong(paytime)));
            params.put("dsp_id", sid);
            params.put("resultType", true);
            params.put("limit", true);
            List<ReportDTO> list = reportService.list(params);
            if (CollectionUtil.isEmpty(list)) {
                log.info("dspId:{} 订单号:{} 未匹配到合适的点击", sid, orderCallBackRequest.getOrderid());
                return null;
            }
            ReportDTO reportDTO = list.get(0);
            AccountDTO accountDTO = AccountLocalCache.getInstance().get(sid);
            if (null == accountDTO) {
                log.info("dspId:{} 订单号:{} 未匹配到合适的广告位", sid, orderCallBackRequest.getOrderid());
                return null;
            }
            if (accountDTO.getMediaChannel().equals(MediaChannelConstant.KS)) {
                ksCallback(orderCallBackRequest, reportDTO);
            } else if (accountDTO.getMediaChannel().equals(MediaChannelConstant.TOU_TIAO)) {
                toutiao(orderCallBackRequest, reportDTO);
            } else if (accountDTO.getMediaChannel().equals(MediaChannelConstant.HW)) {
                huawei(orderCallBackRequest, reportDTO);
            } else {
                log.error("媒体未配置");
                return null;
            }
            //和点击追踪绑定
            String value = String.valueOf(System.currentTimeMillis());
            String eventType = "3";
            reportDTO.setResultType(eventType);
            reportDTO.setResultTime(value);
            reportDTO.setSid(orderCallBackRequest.getSid());
            reportDTO.setAppkey(orderCallBackRequest.getAppkey());
            reportDTO.setActId(orderCallBackRequest.getActId());
            reportDTO.setUpdateTime(new Date());
            reportService.updateData(reportDTO,eventType);
            //更新订单状态标识已推送
            updateOrderStatus(meituanOrderDTO.getId());
            log.info("dspId:{} 订单号:{} 处理成功", sid, orderCallBackRequest.getOrderid());
        } catch (Exception e) {
            log.error("快手美团 出现异常的 dspId:{} 订单号为{} ", orderCallBackRequest.getSid(), orderCallBackRequest.getOrderid());
            log.error("快手美团 处理快手-美团出现了异常，异常的错误为", e);
        }
        return new MeiTuanResponse().ok();
    }

    private void huawei(OrderCallBackRequest orderCallBackRequest, ReportDTO reportDTO) {
        Long eventTime = Long.parseLong(orderCallBackRequest.getPaytime()) * 1000;
        reportDTO.setResultType(String.valueOf(eventTime));
        AccountDTO accountDTO = AccountLocalCache.getInstance().get(reportDTO.getDspId());

        log.info("从数据库查询的数据为{}", JsonUtils.toJsonString(reportDTO));
        //2.回调渠道，调用华为回传接口
        Long conversion_time = System.currentTimeMillis()/ 1000;
        HwUploadRequest hwUploadRequest = new HwUploadRequest();
        hwUploadRequest.setOaid(reportDTO.getOaid());
        hwUploadRequest.setConversion_type("paid");
        hwUploadRequest.setTimestamp(String.valueOf(System.currentTimeMillis()));
        hwUploadRequest.setCallback(reportDTO.getCallback());
        hwUploadRequest.setCampaign_id(reportDTO.getCampaignId());
        hwUploadRequest.setContent_id(reportDTO.getContentId());

        hwUploadRequest.setConversion_time(String.valueOf(conversion_time));
        hwUploadRequest.setTracking_enabled("1");
        String paramsBody = JsonUtils.toJsonString(hwUploadRequest);

        log.info("账号为【{}】，mt给华为请求的参数为{}", reportDTO.getDspId(), paramsBody);
        Map<String, String> header = new HashMap<>();

        header.put("Authorization", HwSecureUtil.buildAuthorizationHeader(paramsBody, accountDTO.getSspKey()));

        HttpRequest body = HttpUtil.createPost(accountDTO.getSspApiUrl()).addHeaders(header).body(paramsBody);
        String result = body.execute().body();
        log.info("账号为【{}】，mt接收华为转换响应的结果为{}", reportDTO.getDspId(), result);
    }


    /**
     * ]
     *
     * @param orderCallBackRequest
     * @param reportDTO
     */
    public void ksCallback(OrderCallBackRequest orderCallBackRequest, ReportDTO reportDTO) {
        //2.从缓存加载配置
        AccountDTO accountDTO = AccountLocalCache.getInstance().get(reportDTO.getDspId());
        String dspSalt = accountDTO.getDspSalt();

        Long eventTime = Long.parseLong(orderCallBackRequest.getPaytime()) * 1000;
        //2.回调渠道，调用快手回传接口
        Map<String, Object> reqParams = new HashMap<>();
        reqParams.put("event_type", dspSalt);
        reqParams.put("event_time", eventTime);
        reqParams.put("purchase_amount", Double.valueOf(orderCallBackRequest.getTotal()));
        //组装参数和url
        String urlParams = URLUtil.buildQuery(reqParams, StandardCharsets.UTF_8);
        String finalReqUrl = reportDTO.getCallback() + "&" + urlParams;
        log.info("账户号【{}】，快手美团-进行快速回调的请求参数为{}", reportDTO.getDspId(), finalReqUrl);
        String result = HttpUtil.createGet(finalReqUrl).execute().body();
        log.info("账户号【{}】，快手美团-转换响应的结果为-{}", reportDTO.getDspId(), result);


    }

    public void toutiao(OrderCallBackRequest orderCallBackRequest, ReportDTO reportDTO) {
        String url = URLEncoderDecoderTool.decodeURL(reportDTO.getCallback());
        StringBuilder sb=new StringBuilder();
        sb.append(url);
        sb.append("&event_type=");
        sb.append("23");
        String resultUrl=sb.toString();
        log.info("账户号{}，头条美团 进行快速回调的请求参数为{}", reportDTO.getDspId(), resultUrl);
        String result = HttpUtil.createGet(resultUrl).execute().body();
        log.info("账户号{}，头条美团 的转换响应的结果为-{}", reportDTO.getDspId(), result);
    }


    public void updateOrderStatus(Long id) {
        //更新订单状态为已处理
        MeituanOrderEntity meituanOrderEntity = new MeituanOrderEntity();
        meituanOrderEntity.setId(id);
        meituanOrderEntity.setHandType(1);
        meituanOrderService.updateById(meituanOrderEntity);
    }

    public static void main(String[] args) {
        System.out.println(getCurrentDayEndStime());
    }

}
